package com.gitee.grower.util.germ.germ

import ac.github.oa.taboolib.common.reflect.Reflex.Companion.invokeMethod
import ac.github.oa.taboolib.common.reflect.Reflex.Companion.setProperty
import com.germ.germplugin.api.KeyType
import com.germ.germplugin.api.dynamic.gui.GermGuiOptions
import com.germ.germplugin.api.dynamic.gui.GermGuiPart
import com.germ.germplugin.api.dynamic.gui.GermGuiScreen
import com.germ.germplugin.api.dynamic.gui.IGuiPartCallback
import com.germ.germplugin.api.dynamic.gui.IGuiScreenHandler
import com.germ.germplugin.api.yaml.YamlBeans
import com.gitee.grower.util.germ.createDSL
import org.bukkit.configuration.file.YamlConfiguration
import org.bukkit.entity.Player
import taboolib.library.configuration.ConfigurationSection
import java.util.UUID

class GermScreenDSL {

    var name = UUID.randomUUID().toString()

    var startX = "1"
    var startY = "1"
    var startZ = "0"

    var guide = false

    val openDos = mutableListOf<String>()

    val parts = mutableListOf<GermPartDSL<*>>()

    var closed: ((Player, GermGuiScreen) -> Unit)? = null

    var drag: GermGuiOptions.Drag? = null

    val map = mutableMapOf<String, Any>()

    val keyHandlers = mutableMapOf<KeyType, (Player, GermGuiScreen) -> Unit>()

    var private: org.bukkit.configuration.ConfigurationSection? = null

    fun infuse(config: ConfigurationSection) {
        this.name = config.name
        config.getString("options.startX")?.let { this.startX = it }
        config.getString("options.startY")?.let { this.startY = it }
        config.getString("options.startZ")?.let { this.startZ = it }
        config.getString("options.guide")?.let { this.startZ = it }

        openDos += config.getStringList("options.openDos")
        config.getKeys(false).forEach {
            if (it.startsWith('_')) {
                parts += createDSL<GermPartDSL<*>>(config.getConfigurationSection(it)!!)
            }
        }
        private = toBukkitConfigurationSection(config.getConfigurationSection("private"))
        config.getConfigurationSection("drag")?.let {
            this.drag = GermGuiOptions.Drag()
            this.drag!!.height = it.getString("height")
            this.drag!!.width = it.getString("width")
            this.drag!!.locationX = it.getString("locationX")
            this.drag!!.locationY = it.getString("locationY")
        }

    }

    fun toBukkitConfigurationSection(root: ConfigurationSection?): YamlConfiguration {
        val configuration = YamlConfiguration()

        if (root == null) return configuration

        root.getKeys(false).forEach {
            if (root.isConfigurationSection(it)) {
                configuration[it] = toBukkitConfigurationSection(root.getConfigurationSection(it)!!)
            } else {
                configuration[it] = root.get(it)
            }
        }
        return configuration
    }

    fun addKeyHandler(key: KeyType, call: (Player, GermGuiScreen) -> Unit) {
        keyHandlers[key] = call
    }

    fun create(): GermGuiScreen {

        val germGuiScreen = GermGuiScreen(name)

        germGuiScreen.options.startX = startX
        germGuiScreen.options.startY = startY
        germGuiScreen.options.startZ = startZ
        germGuiScreen.options.isGuide = guide
        germGuiScreen.options.openDos = openDos

        germGuiScreen.invokeMethod<Void>("setPrivateConfig",private)

        parts.forEach {
            germGuiScreen.addGuiPart(it.create() as GermGuiPart<*>)
        }
        if (closed != null) {
            germGuiScreen.closedHandler = IGuiScreenHandler { p0, p1 -> closed!!(p0, p1) }
        }

        keyHandlers.forEach {
            germGuiScreen.registerKeyDownHandler(it.key) { player, screen ->
                it.value(player, screen)
            }
        }


        return germGuiScreen
    }

}